Skip to content

[4.x] TenancyUrlGenerator: override toRoute()#1439

Open
lukinovec wants to merge 8 commits intomasterfrom
override-toroute
Open

[4.x] TenancyUrlGenerator: override toRoute()#1439
lukinovec wants to merge 8 commits intomasterfrom
override-toroute

Conversation

@lukinovec
Copy link
Copy Markdown
Contributor

@lukinovec lukinovec commented Mar 9, 2026

This PR adds the toRoute() method override to TenancyUrlGenerator. toRoute() now attempts to find a tenant equivalent of the passed route (= a route with the same name as the passed one, but with the tenant prefix) and generates URL for the tenant route. This behavior can be bypassed using the bypass parameter, like with the route() method override TenancyUrlGenerator had until now.

The primary reason for adding this is that Livewire v4 no longer uses the route() helper (which automatically prefixes the passed route name because of the override in TenancyUrlGenerator) in Livewire::getUpdateUri(). Now, it uses toRoute() (livewire/livewire@544aa3d#diff-e7609f8b0a60bde5a85067803d4e2f08f235c7cee9225a51ea67a85ff9a1d694R52), which didn't automatically swap the route for its 'tenant.'-prefixed equivalent in tenant context (until now). So for the Livewire integration to work with path identification, we need to override toRoute() as described.

The temporarySignedRoute() override got removed because temporarySignedRoute() calls route() under the hood, there's no need to specifically override temporarySignedRoute().

Note: Browsing old convos, it seems like the temporarySignedRoute() override was needed to make Livewire file uploads work with path identification, but it's not needed anymore. TenancyUrlGenerator had some changes since then, and now, I can't see the exact reason why we needed the override (temporarySignedRoute() uses route() under the hood, so the only thing that should really matter is overriding route()/toRoute()). It was likely a leftover from some older implementation.

The route() override got simplified. Since route() uses toRoute() under the hood, the route() override only has to have the prefixing logic. The rest is delegated to toRoute().

Note: Even though we override toRoute() now which route() uses for generating the URLs, we still need to override route() for its $this->routes->getByName($name) call to receive the prefixed name. For example, if route() wasn't overridden, and we only had one route: tenant.foo (no central foo route), and we'd call route('foo'), we'd get an exception saying that route "foo" wasn't found, even if automatic route name prefixing was enabled and toRoute() was overridden. With the route() override, route('foo') acts as if we passed 'tenant.foo' instead of 'foo'.

Comments in TenancyUrlGenerator and UrlGeneratorBootstrapper got updated to be more accurate. All intentionally affected methods are listed in TenancyUrlGenerator's docblock.

Summary by CodeRabbit

  • Improvements

    • Unified URL generation flow so route-name prefixing and tenant-parameter injection apply consistently across more URL entry points; bypass handling now reliably skips these behaviors when requested.
  • Documentation

    • Clarified docblock wording to more precisely describe how tenant parameters are included in generated links.
  • Tests

    • Added tests verifying prefixed-route selection, tenant-parameter injection for unnamed routes, and bypass behavior.

Also update `route()` override since `parent::route()` calls `toRoute()` under the hood (similarly to how `parent::temporarySignedRoute()` calls `route()`)
@lukinovec lukinovec marked this pull request as ready for review March 9, 2026 12:39
@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.06%. Comparing base (c32f52c) to head (ac90ef0).

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1439      +/-   ##
============================================
+ Coverage     86.03%   86.06%   +0.02%     
- Complexity     1156     1157       +1     
============================================
  Files           184      184              
  Lines          3381     3380       -1     
============================================
  Hits           2909     2909              
+ Misses          472      471       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

lukinovec and others added 3 commits March 10, 2026 12:17
The `toRoute()` and `route()` overrides cover `temporarySignedRoute())`, so we don't need to specifically override `temporarySIgnedRoute()` anymore. `route()` override got simplified since everything except for the name prefixing is delegated to the lower-level `toRoute()` method.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

Centralized route-name prefixing and tenant-parameter handling by introducing a toRoute() override and adjusting route() to normalize inputs; a docblock wording change clarifies tenant-parameter placement. Tests added to validate toRoute() prefixing and bypass/tenant-parameter behaviors. No public signatures were widened.

Changes

Cohort / File(s) Summary
Bootstrapper docblock
src/Bootstrappers/UrlGeneratorBootstrapper.php
Docblock reworded to clarify that the tenant parameter (from PathTenantResolver::tenantParameterName()) is passed to links produced by URL-generation methods. No executable code changed.
URL generator core
src/Overrides/TenancyUrlGenerator.php
Reworked route handling: removed the temporarySignedRoute() override and added toRoute($route, $parameters, $absolute). route() now focuses on validating/normalizing route names and delegates parameter preparation; toRoute() handles deriving/applying tenant-prefixed route names, swaps to the prefixed route when present, and delegates to parent::toRoute(). prepareRouteInputs() accepts an optional name and centralizes tenant-parameter injection and bypass-parameter removal.
Tests
tests/Bootstrappers/UrlGeneratorBootstrapperTest.php
Added tests covering url()->toRoute() behavior: tenant-prefixed route selection when $prefixRouteNames = true, bypass parameter preventing prefixing, tenant query-parameter injection for unnamed routes when enabled, and bypass preventing tenant-parameter addition.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I bound along each named and nameless road,
I tuck a tenant tag where query-strings go,
toRoute() hops, and prefixes find their nest,
A bypass lets the central path stay blessed,
I leave soft footprints on every generated URL.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding an override of toRoute() to TenancyUrlGenerator, which is the core refactor to support Livewire v4's shift from route() to toRoute().
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch override-toroute

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Overrides/TenancyUrlGenerator.php`:
- Around line 141-149: The parameter mutation is skipped for unnamed Route
objects because $route->getName() gates the call to prepareRouteInputs; change
the logic in TenancyUrlGenerator::toRoute so you always call
$this->prepareRouteInputs($name, Arr::wrap($parameters)) (or call it with
null/$name when route has no name) to apply tenant-parameter injection and
bypass-parameter removal, but keep the route swap conditional: only replace
$route when $prefixedName !== $name and $this->routes->getByName($prefixedName)
returns a route; ensure prepareRouteInputs and the passTenantParameterToRoutes
behavior run even when $route->getName() is falsy before delegating to
parent::toRoute().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 17d8031d-e2be-43de-9b4c-44e8b71136d2

📥 Commits

Reviewing files that changed from the base of the PR and between 60dd522 and dc2be5b.

📒 Files selected for processing (3)
  • src/Bootstrappers/UrlGeneratorBootstrapper.php
  • src/Overrides/TenancyUrlGenerator.php
  • tests/Bootstrappers/UrlGeneratorBootstrapperTest.php

Comment thread src/Overrides/TenancyUrlGenerator.php
If an unnamed route is passed to url()->toRoute(), the generated URL will receive the tenant parameter as long as the bypass parameter wasn't passed. Also remove the bypass parameter from the generated URL.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Overrides/TenancyUrlGenerator.php`:
- Around line 128-130: The route() method currently calls prepareRouteInputs()
and discards the mutated $parameters, causing duplicate work and potential side
effects; create a small helper (e.g., normalizeRouteName or prepareRouteName) in
the TenancyUrlGenerator class that performs only the name normalization logic
extracted from prepareRouteInputs() and returns the normalized $name without
mutating $parameters, then update route() to call that helper and pass the
original $parameters into parent::route($name, $parameters, $absolute); keep
prepareRouteInputs() and toRoute() unchanged so full parameter resolution still
happens only when needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1ef2ed10-fc71-412c-80f0-c96ee9ac799c

📥 Commits

Reviewing files that changed from the base of the PR and between dc2be5b and bff74c8.

📒 Files selected for processing (2)
  • src/Overrides/TenancyUrlGenerator.php
  • tests/Bootstrappers/UrlGeneratorBootstrapperTest.php

Comment thread src/Overrides/TenancyUrlGenerator.php
@lukinovec
Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 13, 2026

✅ Actions performed

Full review triggered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants